package com.liy.supercloud.server.gateway.task;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.liy.framework.common.redis.utils.RedisUtils;
import com.liy.framework.common.utils.DateUtil;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@AutoConfigureAfter({RedisUtils.class})
public class GatewayCountTimer {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RedisUtils redisUtils;

    private static Long REQ_RESPONSE_MAXTIME = 0L;

    private static String TOTAL_KEY = "gtw:req:total";
    private static String SUCCESS_KEY = "gtw:req:success";
    private static String FAILURE_KEY = "gtw:req:failure";
    private static String DETAIL_KEY = "gtw:req:detail";
    private static String RESPONSE_MAXTIME_KEY = "gtw:req:maxoktime";


    private static Long REQ_TOTAL = 0L;
    private static Long REQ_DAY_TOTAL = 0L;
    private static Long REQ_SUCCESS = 0L;
    private static Long REQ_FAILURE = 0L;
    private static Long REQ_TOTAL_NUMBER_PRE = -1L;
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    private static Map<String, JSONObject> preDayJson = new HashMap();
    private static String REQ_COUNT_KEY = "gtw:req:count";
    private static Map<String, Integer> reqCountMap1 = new HashMap();
    private static Map<String, JSONObject> reqCountMap2 = new HashMap();

    public GatewayCountTimer() {
    }

    @Scheduled(
            fixedRate = 10000L
    )
    public void updateRedis() throws JSONException {
        if (REQ_TOTAL_NUMBER_PRE != REQ_TOTAL) {
            REQ_TOTAL_NUMBER_PRE = REQ_TOTAL;
            this.redisUtils.set(TOTAL_KEY, REQ_TOTAL);
            this.redisUtils.set(SUCCESS_KEY, REQ_SUCCESS);
            this.redisUtils.set(FAILURE_KEY, REQ_FAILURE);
            this.redisUtils.set(RESPONSE_MAXTIME_KEY, REQ_RESPONSE_MAXTIME);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            Date curDate = calendar.getTime();
            calendar.add(5, -1);
            Date preDate = calendar.getTime();
            String preDateStr = sdf.format(preDate);
            JSONObject oldJson = (JSONObject)preDayJson.get(preDateStr);
            if (oldJson == null) {
                Object obj = this.redisUtils.hget(DETAIL_KEY, sdf.format(preDate));
                if (obj != null) {
                    oldJson = JSONObject.parseObject(obj.toString());
                } else {
                    oldJson = new JSONObject();
                    oldJson.put("total", 0);
                    oldJson.put("success", 0);
                    oldJson.put("failure", 0);
                }

                preDayJson = new HashMap();
                preDayJson.put(preDateStr, oldJson);
            }

            JSONObject json = new JSONObject();
            REQ_DAY_TOTAL = REQ_TOTAL - oldJson.getLong("total");
            json.put("total", REQ_DAY_TOTAL);
            json.put("success", REQ_SUCCESS - oldJson.getLong("success"));
            json.put("failure", REQ_FAILURE - oldJson.getLong("failure"));
            this.redisUtils.hset(DETAIL_KEY, sdf.format(curDate), json.toString());
            this.log.info("Update request total number successfully: " + REQ_TOTAL);
        }

    }

    @Bean
    public Long initRequestCount() {
        Object total = this.redisUtils.get(TOTAL_KEY);
        Object success = this.redisUtils.get(SUCCESS_KEY);
        Object failure = this.redisUtils.get(FAILURE_KEY);
        Object resptime = this.redisUtils.get(RESPONSE_MAXTIME_KEY);
        if (total != null) {
            REQ_TOTAL = Long.parseLong(total.toString());
        }

        if (success != null) {
            REQ_SUCCESS = Long.parseLong(success.toString());
        }

        if (failure != null) {
            REQ_FAILURE = Long.parseLong(failure.toString());
        }

        if (resptime != null) {
            REQ_RESPONSE_MAXTIME = Long.parseLong(resptime.toString());
        }

        this.log.info("Init request total number successfully: " + REQ_TOTAL);
        return REQ_TOTAL;
    }

    public static synchronized Long getNextRequestTotalNumber() {
        Long var0 = REQ_TOTAL;
        REQ_TOTAL = REQ_TOTAL + 1L;
        return REQ_TOTAL;
    }

    public static synchronized Long getNextRequestSuccessNumber() {
        Long var0 = REQ_SUCCESS;
        REQ_SUCCESS = REQ_SUCCESS + 1L;
        return REQ_SUCCESS;
    }

    public static synchronized Long getNextRequestFailureNumber() {
        Long var0 = REQ_FAILURE;
        REQ_FAILURE = REQ_FAILURE + 1L;
        return REQ_FAILURE;
    }

    public static synchronized void setResponseMaxTimer(long timer) {
        String key = DateUtil.getTimeNow("yyyyMMddhhmmss");
        int count = (Integer)reqCountMap1.getOrDefault(key, 0);
        reqCountMap1.put(key, count++);
        if (timer > REQ_RESPONSE_MAXTIME) {
            REQ_RESPONSE_MAXTIME = timer;
        }

    }

    public static Map<String, Object> getCountInfo() {
        Map<String, Object> map = new HashMap();
        Double rate = Double.valueOf((double)REQ_SUCCESS) / Double.valueOf((double)REQ_TOTAL) * 100.0D;
        map.put("total", REQ_TOTAL);
        map.put("dayTotal", REQ_DAY_TOTAL);
        map.put("success", REQ_SUCCESS);
        map.put("failure", REQ_FAILURE);
        map.put("maxtime", REQ_RESPONSE_MAXTIME);
        map.put("successRate", (new DecimalFormat("#.00")).format(rate));
        return map;
    }
}
